import os
import sqlite3
from pathlib import Path
import argparse
import shutil
import time

def check_and_connect_db(db_path):
    """检查并连接到SQLite数据库"""
    conn = sqlite3.connect(db_path)
    # 设置sqlite3.Row作为行工厂，以便能够使用字典访问字段
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    return conn, cursor

def fetch_existing_records(conn, cursor):
    """从zip_hash表中获取所有记录"""
    cursor.execute('SELECT file_path, file_name FROM zip_hash')
    records = {f"{row['file_path']}|{row['file_name']}" for row in cursor.fetchall()}
    return records

def scan_zip_files(scan_dir):
    """扫描指定目录及其子目录下的所有ZIP文件，并生成其file_path和file_name"""
    scan_dir_path = Path(scan_dir)
    backup_dir = scan_dir_path / 'backup'
    
    zip_files = []
    for zip_file in scan_dir_path.rglob('*.zip'):
        if str(zip_file).startswith(str(backup_dir)):
            continue  # Skip files in the backup directory
        relative_path = str(zip_file.relative_to(scan_dir_path).parent)  # 获取相对路径但不包括文件名
        file_name = zip_file.name  # 单独获取文件名
        zip_files.append((relative_path, file_name))
    
    return zip_files

def generate_backup_path(backup_dir, file_name):
    """生成一个唯一的备份路径，处理文件名冲突"""
    timestamp = int(time.time())
    base_name, ext = os.path.splitext(file_name)
    backup_path = backup_dir / f"{base_name}.{timestamp}{ext}"
    counter = 1
    
    while backup_path.exists():
        backup_path = backup_dir / f"{base_name}.{timestamp}_{counter}{ext}"
        counter += 1
    
    return backup_path

def move_to_backup(zip_file, scan_dir):
    """将指定的ZIP文件移动到备份目录，并处理文件名冲突"""
    scan_dir_path = Path(scan_dir)
    backup_dir = scan_dir_path / 'backup'
    backup_dir.mkdir(parents=True, exist_ok=True)

    target_path = generate_backup_path(backup_dir, zip_file.name)
    try:
        shutil.move(str(zip_file), str(target_path))
        print(f"已移动文件: {zip_file} 到 {target_path}")
    except Exception as e:
        print(f"移动文件 {zip_file} 时出错: {e}")

def main(db_directory, scan_dir):
    db_path = str(Path(db_directory) / 'file_hashes.db')
    conn, cursor = check_and_connect_db(db_path)

    existing_records = fetch_existing_records(conn, cursor)
    zip_files = scan_zip_files(scan_dir)

    for file_path, file_name in zip_files:
        key = f"{file_path}|{file_name}"
        if key not in existing_records:
            zip_file_path = Path(scan_dir) / file_path / file_name
            move_to_backup(zip_file_path, scan_dir)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="扫描变更目录中的所有ZIP文件，若在zip_hash表中找不到对应记录，则将文件移动到备份目录")
    parser.add_argument('--db', required=True, help="SQLite数据库存放位置")
    parser.add_argument('--scan-dir', required=True, help="变更目录")

    args = parser.parse_args()

    db_directory = args.db
    scan_dir = args.scan_dir

    main(db_directory, scan_dir)